import mod_item,mod_actor,mod_player,mod_verbs,mod_line
from mod_brain import Brain,Memory,BaseLevelMemory
import random
import mod_direction

class FakeMapIterator:
    def __init__(self,fakeMap):
        self.fakeMap = fakeMap
        self.tileIter = fakeMap.levelMemory.visibleTiles.__iter__()
    
    def next(self):
        next = None
        while not next:
            potentialTile = self.tileIter.next()
            result = self.fakeMap.get(potentialTile)
            if result:
                next = potentialTile
        return next
    
    def __iter__(self):
        return self

class FakeMap:
    def __init__(self,actualMap,levelMemory):
        self.actualMap = actualMap
        self.levelMemory = levelMemory
    
    def __getitem__(self,key):
        result = self.get(key)
        if result:
            return result
        else:
            raise KeyError
    
    def get(self,key):
        # Abstract
        pass
    
    def __iter__(self):
        return FakeMapIterator(self)
    
    def __contains__(self,item):
        result = self.get(item)
        if result:
            return True
        else:
            return False

class MirrorEntityMap(FakeMap):   
    def get(self,key):
        entity = self.actualMap.get(key)
        if entity and (entity.structural or key in self.levelMemory.visibleTiles):
            return entity
        else:
            return None

class MirrorItemMap(FakeMap):
    def __init__(self,actualItemMap,levelMemory):
        self.actualItemMap = actualItemMap
        self.levelMemory = levelMemory
    
    def get(self,key):
        actualItems = self.actualItemMap.get(key)
        if actualItems and key in self.levelMemory.visibleTiles:
            def filterFunct(item): return item.visible
            seenItems = filter(filterFunct,actualItems)
            if seenItems:
                return seenItems
            else:
                return None
        else:
            return None
        

class MirrorLevelMemory(BaseLevelMemory):
    def __init__(self,level):
        BaseLevelMemory.__init__(self,level.number)
        self.itemMap = MirrorItemMap(level.itemMap,self)
        self.entityMap = MirrorEntityMap(level.entityMap,self)
        self.spaceMap = level.spaceMap

class MirrorMemory(Memory):
    def __init__(self):
        Memory.__init__(self,MirrorLevelMemory)
    
    def updateVisibility(self,level,refreshAll=False):
        levelMemory = self.levelMemoryMap.get(level.number)
        if not levelMemory:
            levelMemory = MirrorLevelMemory(level)
            self.levelMemoryMap[level.number] = levelMemory
        levelMemory.updateVisibility(self,level,refreshAll)

class PlayerHuntingMemory(MirrorMemory):
    def __init__(self):
        MirrorMemory.__init__(self)
        self.lastPlayerLoc = None
    
    def updateGhost(self,newGhost,level):
        MirrorMemory.updateGhost(self,newGhost,level)
        # Temporary:
        if newGhost.glyph == 'PLAYER':
            self.lastPlayerLoc = newGhost.location
            #print 'Enemy alerted to player position!'

class AIBrain(Brain):
    def __init__(self,actor):
        Brain.__init__(self,actor,PlayerHuntingMemory())
    
    def takeTurn(self):
        Brain.takeTurn(self)
        self.generateDistanceMap()

    def moveRandomly(self):
        reachableTiles = self.getReachableTiles()
        if reachableTiles:
            newSpace = random.choice(list(reachableTiles))
            self.travel(newSpace)
    
    def findClosestTile(self,possibleTiles):
        closestTile = None
        closestDistance = None
        for tile in possibleTiles:
            distance = self.getDistance(tile)
            if distance and (closestDistance == None or distance < closestDistance):
                closestTile = tile
                closestDistance = distance
        return closestTile
        